<template>
  <div class="editor">
    <div class="editor-top">
      <el-button type="primary" @click="handleExport">导出Schema</el-button>
    </div>
    <div class="editor-content">
      <div class="editor-content__left">
        <component-library drag-group="listComponentsGroup" />
      </div>
      <div class="editor-content__center">
        <el-form
          style="height: 100%"
          :model="rootFormData"
          v-bind="formProps"
          class="genFromComponent"
          :class="{
            layoutColumn: !formProps.inline,
            [`layoutColumn-${formProps.layoutColumn}`]: !formProps.inline,
            formInlineFooter: formProps.inlineFooter,
            formInline: formProps.inline
            // [`genFromComponent_${schema.id}Form`]: !!schema.id,
          }"
        >
          <NestedEditor
            v-model:component-list="componentList"
            :drag-options="dragOptions"
            :form-data="rootFormData"
            :form-props="formProps"
          >
            <el-form-item
              v-if="componentList.length > 0 && formFooter.show"
              :style="{
                display:
                  formProps.inline && formProps.inlineFooter
                    ? 'inline-block'
                    : 'block'
              }"
              class="formFooter_item w100 formFooter_item-editor"
            >
              <el-button @click="$emit('onCancel')">{{
                formFooter.cancelBtn
              }}</el-button>
              <el-button type="primary" @click="$emit('onSubmit')">
                {{ formFooter.okBtn }}
              </el-button>
            </el-form-item>
          </NestedEditor>
        </el-form>
      </div>
      <div class="editor-content__right">
        <el-tabs v-model="activeName">
          <el-tab-pane v-if="curEditorItem" label="组件配置" name="compConfig">
            <VueJsonFrom
              v-model="curEditorItem.componentValue"
              :class="$style.configForm"
              :schema="curEditorItem.componentPack.propsSchema"
              :form-props="{
                labelPosition: 'right',
                labelWidth: '110px'
              }"
              :form-footer="{
                show: false
              }"
            >
            </VueJsonFrom>
          </el-tab-pane>
          <el-tab-pane label="表单配置" name="formConfig">
            <VueJsonFrom
              v-model="formConfig"
              :class="$style.configForm"
              :schema="FormConfSchema"
              :form-props="{
                labelPosition: 'right',
                labelWidth: '110px'
              }"
              :form-footer="{
                show: false
              }"
            >
            </VueJsonFrom>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
    <el-dialog v-model="showSchema" title="schema显示">
      <ExportSchemaView :gen-code="genCode" />
    </el-dialog>
  </div>
</template>

<script lang="ts">
export default {
  name: 'FormEditor'
}
</script>
<script setup lang="ts">
import VueForm from '@lljj/vue3-form-element'

import FormContent from '@/form-editor/components/form-content.vue'
import ComponentLibrary from '@/form-editor/components/component-library.vue'
import VueJsonFrom from '@lljj/vue3-form-element'
import FormConfSchema from './view-components/FormConf'
import ExportSchemaView from './components/ExportSchemaView.vue'
import {
  componentList2JsonSchema,
  formatFormLabelWidth
} from './common/editorData'
import NestedEditor from './components/NestedEditor.vue'

const activeName = ref('formConfig')

const curEditorItem = ref(false)
const setCurEditorItem = (editorItem: boolean) => {
  activeName.value = editorItem ? 'compConfig' : 'formConfig'
  curEditorItem.value = editorItem
}

const formConfig = ref<Record<string, any>>({})
const componentList = ref<any[]>([])

const showSchema = ref(false)
const genCode = ref({})
const handleExport = () => {
  showSchema.value = true
  console.log('componentList', componentList)
  console.log(generateCode())
  genCode.value = generateCode()
}

const formProps = computed(() => {
  if (!formConfig.formProps) {
    return {}
  }
  return {
    ...formConfig.formProps,
    labelWidth: formatFormLabelWidth(formConfig.formProps.labelWidth)
  }
})
const formFooter = computed(() => {
  return formConfig.formFooter || {}
})
const generateCode = () => {
  // const { formFooter, formProps } = this
  const defaultConfig = {
    formFooter: {
      show: true,
      okBtn: '保存',
      cancelBtn: '取消'
    },
    formProps: {
      inline: false,
      inlineFooter: false,
      layoutColumn: 1,
      labelPosition: 'top'
    }
  }

  // 不做深度
  const filter = (obj: any, defaultObj: any) =>
    Object.keys(obj).reduce((pre, cur) => {
      if (!(obj[cur] === defaultObj[cur])) {
        pre[cur] = obj[cur]
      }
      return pre
    }, {})

  return {
    schema: componentList2JsonSchema(componentList.value),
    uiSchema: {},
    formFooter: filter(formFooter.value, defaultConfig.formFooter),
    formProps: filter(formProps.value, defaultConfig.formProps)
  }
}

const rootFormData = ref({})

const dragOptions = {
  animation: 300,
  group: 'listComponentsGroup',
  disabled: false,
  ghostClass: 'ghostItem',
  // filter: $style.disabled,
  draggable: '.draggableItem',
  tag: 'div',
  swapThreshold: 0.3
  // forceFallback: true
  // fallbackTolerance: 0
}

const formData = ref({})
const handleSubmit = (e: any) => {
  console.log(e, formData)
}

const schema = {
  title: 'UserInfo 表单',
  description: 'A simple form example.',
  type: 'object',
  required: ['firstName', 'lastName'],
  properties: {
    firstName: {
      type: 'string',
      title: 'First name',
      default: 'Jun'
    },
    lastName: {
      type: 'string',
      title: 'Last name'
    },
    age: {
      type: 'integer',
      title: 'Age',
      maximum: 80,
      minimum: 16
    },
    bio: {
      type: 'string',
      title: 'Bio',
      minLength: 10
    },
    password: {
      type: 'string',
      title: 'Password',
      minLength: 3
    },
    telephone: {
      type: 'string',
      title: 'Telephone',
      minLength: 10
    }
  }
}

provide('editorEvent', {
  setCurEditorItem
})
</script>

<style scoped lang="less">
.editor {
  height: 100vh;
  --top-height: 50px;
  --border-style: 1px solid #e5e9ea;
  &-top {
    height: var(--top-height);
    border-bottom: var(--border-style);
  }
  &-content {
    display: flex;
    height: calc(100% - var(--top-height));
    --left-width: 300px;
    --right-width: 400px;
    &__left {
      width: var(--left-width);
      border-right: var(--border-style);
      padding: 10px;
      box-sizing: border-box;
    }
    &__center {
      width: calc(100% - var(--left-width) - var(--right-width));
    }
    &__right {
      width: var(--right-width);
      border-left: var(--border-style);
    }
  }
}
</style>
<style lang="less" module>
.configForm {
  padding: 0 20px;
  & > h3 {
    font-size: 15px;
    font-weight: bold;
  }
}
</style>
